package whu.cn.whushare.ui.main;

import java.util.Stack;

import whu.cn.whushare.R;
import whu.cn.whushare.common.Application;
import whu.cn.whushare.ui.common.MainReShowFragment;
import whu.cn.whushare.ui.main.activity.ActivitiesFragment;
import whu.cn.whushare.ui.main.known.KnownFragment;
import whu.cn.whushare.ui.main.my.LoginActivity;
import whu.cn.whushare.ui.main.my.MyHomeFragment;
import whu.cn.whushare.ui.main.search.SearchFragment;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.SparseArray;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.androidplus.ui.ToastManager;
import com.androidplus.util.ViewMapping;
import com.androidplus.util.ViewMappingUtil;
import com.umeng.message.PushAgent;

/**
 * 文件名：MainTabActivity
 * 描 述：实现MainTab页面功能
 * 作 者：胡平平
 */
@ViewMapping(id = R.layout.main_tab_layout)     //获取main_tab页面布局
@SuppressWarnings("unused")
public class MainTabActivity extends FragmentActivity {
	private FragmentManager mFragmentManager;
    //获取布局文件下方的四个按钮，分别为“活动”、“问答”、“搜索”和“我”
	@ViewMapping(id = R.id.first_btn)
	private Button mFirstBtn;
	@ViewMapping(id = R.id.second_btn)
	private Button mSecondBtn;
	@ViewMapping(id = R.id.third_btn)
	private Button mThirdBtn;
	@ViewMapping(id = R.id.last_btn)
	private Button mLastBtn;

	private final static String[] mTabTags = { "salon", "known", "search", "my" };
	private final static String LAST_TAB = "lastTab"; // 上次最后的tab

	private SparseArray<Tab> mTabs = new SparseArray<Tab>();
	private Tab mTabNow;    //当前tab

	private int mLastTabId;

	private boolean exit; // 退出软件

	@SuppressWarnings("all")    //忽略所有警告


    /*
     * 方法名：getStartIntent(Context context)
     * 功 能：获取跳转到当前activity的intent消息
     * 参 数：@param Context context-上下文信息
     * 返回值：@return 跳转到当前activity的intent
     */
	public static Intent getStartIntent(Context context) {
		Intent intent = new Intent(context, MainTabActivity.class);

		return intent;
	}

	@Override
    /**
     * 重写父类的方法，初始化当前activity
     * @see android.app.Activity#onCreate(android.os.Bundle)
     */
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

        //开启Umeng消息推送服务和统计应用启动数据
		PushAgent pushAgent = PushAgent.getInstance(this);
		pushAgent.onAppStart();
		pushAgent.enable();

		initParams();
		initViews();
		initTabs();
		selectFirstTab();

		pushAgent.onAppStart();
	}

    //初始化参数
	private void initParams() {
	}

    //初始化views
	private void initViews() {
		ViewMappingUtil.mapView(this, this);

        /*
         * 获取与当前activity相关的FragmentManager
         * @see android.support.v4.app.FragmentActivity#getSupportFragmentManager()
         */
		mFragmentManager = getSupportFragmentManager();
	}

    //初始化tabs
	private void initTabs() {
		Button[] buttons = { mFirstBtn, mSecondBtn, mThirdBtn, mLastBtn };
		View.OnClickListener tabClickListener = new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				selectTab((Integer) v.getTag());
			}
		};

        //将附加了id和tag的tab添加到mTabs中，并为tabs添加事件监听器，响应点击事件
		for (int i = 0; i < buttons.length; i++) {
			buttons[i].setTag(i);
			addTab(new Tab(i, mTabTags[i], buttons[i]));
			buttons[i].setOnClickListener(tabClickListener);
		}
	}

    //跳转到LoginActivity
    private void jumpToLoginActivity() {
        getInLogin();
    }
    private void getInLogin() {
        Intent i = LoginActivity.getStartIntent(this);
        startActivity(i);
        finish();
    }

    //重新回到页面时，需显示上次用户选择的tab
	private void selectFirstTab() {
		// when the Activity is recycled，needing to showing the last tab;
		if (mLastTabId > 0 && mLastTabId <= 3)
			selectTab(mLastTabId);
		else
			selectTab(3);   //这里是否应该为0???
	}

	/**
     * 方法名：addTab(Tab tab)
	 * 功 能：添加Tab(注意视图必须有id否则将抛出异常)
     * 参 数：@param Tab tab - 被添加的tab
	 */
	private void addTab(Tab tab) {
		mTabs.put(tab.id, tab);
	}

    /**
     * 方法名：selectTab(int tabId)
     * 功 能：根据tabId跳转到该tabId代表的页面
     * 参 数：@param int tabId - 被选中的tabId
     */
	public void selectTab(int tabId) {
		Tab tab = mTabs.get(tabId);

        // 若选中的Tab没变，则直接返回
		if (mTabNow == tab) {
			return;
		}

		// 若选中的Tab发生变化，则开始一个Fragment事务
		FragmentTransaction transaction = mFragmentManager.beginTransaction();
        // 隐藏当前Tab
        if (mTabNow != null) {
			mTabNow.hide(transaction);
		}
		// 显示被选中的Tab
		tab.show(transaction);

        //执行事务
		transaction.setTransition(FragmentTransaction.TRANSIT_UNSET);
		transaction.commit();
		mFragmentManager.executePendingTransactions();
		mTabNow = tab;
	}

	@Override
    /**
     * 保存当前activity状态
     * @see android.app.Activity#onSaveInstanceState(android.os.Bundle)
     */
	protected void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);
		if (mTabNow != null)
			outState.putInt(LAST_TAB, mTabNow.id);
	}

    /**
     * 处理触屏事件
     * @param ev - 需要被处理的触屏事件
     * @return boolean - 当该触屏事件已被处理时返回true
     * @see android.app.Activity#dispatchTouchEvent(android.view.MotionEvent)
     */
	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
		exit = false;
		return super.dispatchTouchEvent(ev);
	}

    /**
     * 重写返回键操作
     * @param keyCode - 被点击的键码
     * @param event - 键事件
     * @see android.support.v4.app.FragmentActivity#onKeyDown(int, android.view.KeyEvent)
     */
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (keyCode == KeyEvent.KEYCODE_BACK) {
            //若当前fragments.size() > 1，则移除当前fragment并显示上一次选中的fragment
			if (goBack()) {
				return true;
			}
            //若当前fragments.size() = 1，则若exit为true，就推出应用程序，否则弹出提示信息
			if (exit) {
				Application.release(this);
				finish();
			} else {
				makeToast(R.string.main_tab_exit);
				exit = true;
				return true;
			}
		}
		return super.onKeyDown(keyCode, event);
	}

    /**
     * 调用当前tab的goBack函数
     */
	public boolean goBack() {
		return mTabNow.goBack();
	}

    /**
     * 自定义提示信息
     * @param resId - 提示字符串id
     * @see com.androidplus.ui.ToastManager#makeToast(java.lang.String, boolean, boolean)
     */
	private void makeToast(int resId) {
		ToastManager.getInstance(this).makeToast(getString(resId), false, false);
	}

	/**
	 * 在Fragment显示前做相应的处理，通知Fragment已显示
     * @param fragment - 需要进行处理的fragment
     * @see whu.cn.whushare.ui.common.MainReShowFragment#onReShow(whu.cn.whushare.ui.main.MainTabActivity)
	 */
	private void beforeShowFragment(MainReShowFragment fragment) {
		fragment.onReShow(this);
	}

	/**
	 * Tab类
	 */
	private class Tab {
        //tab的id和tag
		private int id;
		private String tag;

		//子Fragment栈
		private Stack<FragmentWrapper> fragments = new Stack<>();

		private TextView view;

        //构造函数，对tab进行初始化
		private Tab(int id, String tag, TextView view) {
			this.id = id;
			this.tag = tag;
			this.view = view;
			init();
		}

		/**
		 * 初始化Tab
		 */
		private void init() {
			FragmentWrapper fragmentWrapper = new FragmentWrapper();
			fragmentWrapper.tag = tag;
			fragmentWrapper.fragment = (MainReShowFragment) Fragment.instantiate(MainTabActivity.this,
					getFragmentClass(tag).getName());
			fragments.push(fragmentWrapper);
		}

		/**
		 * 显示Tab
		 */
		private void show(FragmentTransaction transaction) {
			view.setSelected(true);
			view.setShadowLayer(getResources().getDimension(R.dimen.main_tab_text_shadow_radius), getResources()
					.getDimension(R.dimen.main_tab_text_shadow_dx),
					getResources().getDimension(R.dimen.main_tab_text_shadow_dy),
					getResources().getColor(R.color.main_tab_text_shadow));

			FragmentWrapper fragmentWrapper = fragments.peek();
			MainReShowFragment showFragment = fragmentWrapper.fragment;

			beforeShowFragment(showFragment);

			if (showFragment.isAdded()) {
			    // 已添加过,直接显示Fragment
				transaction.show(showFragment);
			} else {
			    // 未添加过,加入Fragment
				transaction.add(R.id.fragment_layout, showFragment, this.tag);
			}
		}

		/**
		 * 隐藏Tab
		 */
		private void hide(FragmentTransaction transaction) {
			// 取消原Tab对应视图的选中状态
			view.setSelected(false);
			view.setShadowLayer(0, 0, 0, 0);
			transaction.hide(mTabNow.getFragment());
		}

		/**
		 * 返回当前Tab显示中的Fragment
		 *
		 * @return MainReShowFragment
		 */
		private MainReShowFragment getFragment() {
			return this.fragments.peek().fragment;
		}

        /**
         * 方法名：addFragment(String tag, Bundle args)
         * 功 能：将指定类名和参数的fragment添加到group_fragment_layout所在的activity中
         * @param tag - 通过tag获取需要添加的fragment类名
         * @param args - fragment的参数列表
         * @see android.support.v4.app.Fragment#instantiate(android.content.Context, java.lang.String, android.os.Bundle)
         */
		private void addFragment(String tag, Bundle args) {
			FragmentWrapper fragmentWrapper = new FragmentWrapper();
			fragmentWrapper.tag = tag;
			fragmentWrapper.fragment = (MainReShowFragment) Fragment.instantiate(MainTabActivity.this,
					getFragmentClass(tag).getName(), args);

			FragmentTransaction ft = mFragmentManager.beginTransaction();
			ft.hide(fragments.peek().fragment);

			// 栈内如果已有此item，则取出前面的item，再把wrapper压回去。
			while (fragments.search(fragmentWrapper) != -1) {
				ft.remove(fragments.pop().fragment);
			}

			ft.add(R.id.fragment_layout, fragmentWrapper.fragment);
			beforeShowFragment(fragmentWrapper.fragment);
			ft.commit();
			mFragmentManager.executePendingTransactions();
			fragments.push(fragmentWrapper);
		}

		private boolean goBack() {
			if (fragments.size() > 1) {
				FragmentTransaction ft = mFragmentManager.beginTransaction();
				FragmentWrapper fragmentWrapper = fragments.pop();
				MainReShowFragment removeFragment = fragmentWrapper.fragment;
				ft.remove(removeFragment);
				FragmentWrapper showFragmentWrapper = fragments.peek();
				MainReShowFragment showFragment = showFragmentWrapper.fragment;

				beforeShowFragment(showFragment);
				ft.show(showFragment);
				ft.commit();
				mFragmentManager.executePendingTransactions();
				return true;
			}
			return false;
		}

		private Class<? extends Fragment> getFragmentClass(String tag) {
			Class<? extends Fragment> clazz = null;

			if (tag.equals(mTabTags[0]))
				clazz = ActivitiesFragment.class;
			if (tag.equals(mTabTags[1]))
				clazz = KnownFragment.class;
			if (tag.equals(mTabTags[2]))
				clazz = SearchFragment.class;
			if (tag.equals(mTabTags[3]))
				clazz = MyHomeFragment.class;

			return clazz;
		}

		private class FragmentWrapper {
			private MainReShowFragment fragment;
			private String tag;

			@SuppressWarnings("all")
			@Override
            /**
             * 判断对象o是否为FragmentWrapper的实例，
             * 若对象o是当前FragmentWrapper类返回true，
             * 若对象o不是当前FragmentWrapper类实例返回false，
             * 否则对象o是FragmentWrapper类实例，则根据tag值进行处理
             * 若当前FragmentWrapper类的tag非空，且当前FragmentWrapper类的tag与对象o的tag值相等，返回true；
             * 若当前FragmentWrapper类的tag非空，且当前FragmentWrapper类的tag与对象o的tag值不等，返回false；
             * 若当前FragmentWrapper类的tag为空，且对象o的tag值为空，返回true；
             * 若当前FragmentWrapper类的tag为空，且对象o的tag值非空，返回false；
             * @param o - 需要进行比较的对象
             * @see String#equals(java.lang.Object)
             */
			public boolean equals(Object o) {
				if (this == o)
					return true;
				if (!(o instanceof FragmentWrapper))
					return false;

				FragmentWrapper that = (FragmentWrapper) o;

				if (tag != null ? !tag.equals(that.tag) : that.tag != null)
					return false;

				return true;
			}

			@Override
            /**
             * 为当前对象返回一个hash码，原则上，若两个对象通过调用equals方法返回true则应分配相同的hash码
             * 若tag非空，则返回tag的hash码，否则返回0
             * @see Object#hashCode()
             */
			public int hashCode() {
				return tag != null ? tag.hashCode() : 0;
			}
		}
	}
}
